package com.fengye.common.advice;

import com.alibaba.fastjson.JSON;
import com.fengye.common.annotation.ResponseEntity;
import com.fengye.common.domain.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * MyResponseBodyAdvice
 *
 * @author 枫叶fy
 * @description 统一消息体处理
 * @since 2024/7/14 11:45
 */
@Slf4j
@RestControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> {
    // 判断是否使用此advice
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        log.info("supports: returnType={}, converterType={}", returnType, converterType);

        // 检查类是否使用了特定的注解
        if (returnType.getDeclaringClass().isAnnotationPresent(ResponseEntity.class)) {
            return true;
        }

        // 检查方法是否使用了特定的注解
        if ((returnType.getMethod() != null) && returnType.getMethod().isAnnotationPresent(ResponseEntity.class)) {
            return true;
        }

        return false;
    }

    // 返回修改后的body值
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        log.info("beforeBodyWrite: body={}, returnType={}, selectedContentType={}, selectedConverterType={}, request={}, response={}", body, returnType, selectedContentType, selectedConverterType, request, response);

        // 当 body 类型为 string，或者body为null，但是值为null时，需特殊处理，
        // 否则会抛出 java.lang.ClassCastException: Result cannot be cast to java.lang.String 异常
        if ((body == null && returnType.getParameterType().getName().equals("java.lang.String")) || (body instanceof String )) {
            return JSON.toJSON(ResponseResult.success(body)).toString();
        }

        // 如果返回的值不是 ResponseResult，则包装成 ResponseResult，否则直接返回
        if (!(body instanceof ResponseResult)) {
            return ResponseResult.success(body);
        }

        return body;
    }
}
